﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Mvvm;
using System.Collections.ObjectModel;
using System.IO;
using System.Windows.Data;
using System.ComponentModel;
using CodeIn.Diagnostics;
using System.Windows.Controls;
using System.Text.RegularExpressions;
using System.Windows.Input;
using CodeIn.Core;
using CodeIn.Modules.Ui.FileExplorer.ContextMenus;

namespace CodeIn.Modules.Ui.FileExplorer {
	public class FileExplorerItemViewModel : BaseViewModel {
		public enum Types { DRIVE, DIRECTORY, FILE }
		public static FileExplorerItemViewModel DummyItem = FromFile("");

		public ObservableCollection<FileExplorerItemViewModel> Children { get; private set; }
		public Types Type { get; private set; }
		public ContextMenu ContextMenu { get; set; }

		private string path;
		public string Path {
			get { return path; }
			set {
				path = value;
				FirePropertyChanged("Path");
				FirePropertyChanged("Name");
			}
		}

		public string Name {
			get {
				if (Type == Types.DRIVE)
					return path;
				return System.IO.Path.GetFileName(Path);
			}
		}

		private bool isSelected = false;
		public bool IsSelected {
			get { return isSelected; }
			set {
				isSelected = value;
				FirePropertyChanged("IsSelected");
			}
		}

		private bool isExpanded = false;
		public bool IsExpanded {
			get { return isExpanded; }
			set {
				isExpanded = value;
				if (value == true) {
					if (!IsLoaded()) {
						LoadContent();
						if (!IsLoaded())
							isExpanded = false;
					}
				}
				FirePropertyChanged("IsExpanded");
			}
		}

		// --------------------------------------------------------------------
		// Factory
		// --------------------------------------------------------------------

		private FileExplorerItemViewModel(string path) {
			Children = new ObservableCollection<FileExplorerItemViewModel>();
			Path = path;
		}

		public static FileExplorerItemViewModel FromFile(string path) {
			var ret = new FileExplorerItemViewModel(path);
			ret.Type = Types.FILE;

			foreach (var menu in ContextMenus.ContextMenus.Instance.FileMenus)
				if (Regex.IsMatch(path, menu.Filter))
					ret.ContextMenu = menu.Menu;

			return ret;
		}

		public static FileExplorerItemViewModel FromDirectory(string path) {
			var ret = new FileExplorerItemViewModel(path);
			ret.Type = Types.DIRECTORY;
			ret.Children.Add(DummyItem);

			foreach (var menu in ContextMenus.ContextMenus.Instance.DirectoryMenus)
				if (Regex.IsMatch(path, menu.Filter))
					ret.ContextMenu = menu.Menu;

			return ret;
		}

		public static FileExplorerItemViewModel FromDrive(DriveInfo info) {
			var ret = new FileExplorerItemViewModel(info.RootDirectory.FullName);
			ret.Type = Types.DRIVE;
			ret.Children.Add(DummyItem);

			foreach (var menu in ContextMenus.ContextMenus.Instance.DriveMenus)
				if (Regex.IsMatch(info.RootDirectory.FullName, menu.Filter))
					ret.ContextMenu = menu.Menu;

			return ret;
		}

		// --------------------------------------------------------------------
		// Methods
		// --------------------------------------------------------------------

		private void LoadContent() {
			try {
				var dirs = Directory.EnumerateDirectories(path);
				var files = Directory.EnumerateFiles(path);

				Children.Clear();

				foreach (var dir in dirs)
					Children.Add(FileExplorerItemViewModel.FromDirectory(dir));
				foreach (var file in files)
					Children.Add(FileExplorerItemViewModel.FromFile(file));

				CollectionViewSource.GetDefaultView(Children).SortDescriptions.Add(
					new SortDescription("Type", ListSortDirection.Ascending));
				CollectionViewSource.GetDefaultView(Children).SortDescriptions.Add(
					new SortDescription("Name", ListSortDirection.Ascending));
			} catch (IOException ex) {
				MessageHandlers.Debug.WriteErrorLine(ex.Message.Trim());
			}
		}

		private bool IsLoaded() {
			if (Children.Count != 1)
				return true;
			else if (Children[0] != DummyItem)
				return true;
			return false;
		}

		private void LaunchContextMenuAction(ContextMenuAction cmaction) {
			string action = cmaction.Content;
			action = action.Replace("%item_path%", Path);
			action = action.Replace("%item_name%", Name);

			switch (cmaction.Type) {
				case ContextMenuAction.ActionTypes.COMMAND:
					ModuleManager.Instance.CallRaw(action);
					break;

				case ContextMenuAction.ActionTypes.COMMAND_ASYNC:
					ModuleManager.Instance.CallAsync(action);
					break;
			}
		}

		// --------------------------------------------------------------------
		// Commands
		// --------------------------------------------------------------------

		private RelayCommand launchContextMenuActionCommand;
		public ICommand LaunchContextMenuActionCommand {
			get {
				if (launchContextMenuActionCommand == null)
					launchContextMenuActionCommand = new RelayCommand(
						p => { LaunchContextMenuAction((ContextMenuAction)p); },
						p => true);
				return launchContextMenuActionCommand;
			}
		}
	}
}
